﻿using MyGIS;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace test14
{
    public partial class Form1 : Form
    {
        GISDocument Document = new GISDocument();
        GISView View = null;
        Dictionary<GISLayer, ShowAttribute> AllAttwindows = new Dictionary<GISLayer, ShowAttribute>();
        Bitmap BackWindow;
        MOUSECOMMAND MouseCommand = MOUSECOMMAND.Unused;
        int MouseStartX = 0;
        int MouseStartY = 0;
        int MouseMovingX = 0;
        int MouseMovingY = 0;
        int delta = 0;//滚轮滚动的增量值
        bool MouseOnMap = false;//确定鼠标按下和抬起位置都在地图窗口内

        public Form1()
        {
            InitializeComponent();
        }


        /// <summary>
        /// “显示全图”按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ShowMapButton_Click(object sender, EventArgs e)
        {
            if (Document.IsEmpty() || View == null)
                return;
            View.UpdateExtent(Document.extent);
            UpdateMap();
        }


        /// <summary>
        /// 更新地图
        /// </summary>
        internal void UpdateMap()
        {
            if (View == null)
            {
                if (Document.IsEmpty())
                    return;
                View = new GISView(new GISExtent(Document.extent), ClientRectangle);
            }
            if (ClientRectangle.Width * ClientRectangle.Height == 0)//如果窗体最小化则不绘制
                return;
            View.UpdateRectangle(ClientRectangle);//更新当前View的窗口尺寸
            if (BackWindow != null)//根据最新的地图窗口尺寸建立背景窗口
                BackWindow.Dispose();
            BackWindow = new Bitmap(ClientRectangle.Width, ClientRectangle.Height);
            Graphics g = Graphics.FromImage(BackWindow);//在背景窗口上绘图
            g.FillRectangle(new SolidBrush(Color.White), ClientRectangle);
            Document.Draw(g, View);
            Graphics graphics = CreateGraphics();//把背景窗口内容复制到到前景窗口上
            graphics.DrawImage(BackWindow, 0, 0);
            UpdateStatusBar();
        }


        private void MapButtonClick(object sender, EventArgs e)
        {
            GISMapActions actions = GISMapActions.zoomin;
            if ((Button)sender == ZoomInButton) actions = GISMapActions.zoomin;
            else if ((Button)sender == ZoomOutButton) actions = GISMapActions.zoomout;
            else if ((Button)sender == MoveDownButton) actions = GISMapActions.movedown;
            else if ((Button)sender == MoveUpButton) actions = GISMapActions.moveup;
            else if ((Button)sender == MoveLeftButton) actions = GISMapActions.moveleft;
            else if ((Button)sender == MoveRightButton) actions = GISMapActions.moveright;
            View.ChangeView(actions);
            UpdateMap();
        }



        public void OpenAttributeWindow(GISLayer layer)
        {
            ShowAttribute AttributeWindow = null;
            //若属性窗口已存在，就移除记录，稍后统一添加
            if (AllAttwindows.ContainsKey(layer))
            {
                AttributeWindow = AllAttwindows[layer];
                AllAttwindows.Remove(layer);
            }
            //初始化属性窗口
            if (AttributeWindow == null)
                AttributeWindow = new ShowAttribute(layer, this);
            if (AttributeWindow.IsDisposed)//若属性窗口资源被释放
                AttributeWindow = new ShowAttribute(layer, this);
            //添加属性窗口与图层的关联记录
            AllAttwindows.Add(layer, AttributeWindow);
            AttributeWindow.Show();//显示属性窗口
            if (AttributeWindow.WindowState == FormWindowState.Minimized)//若属性窗口最小化
                AttributeWindow.WindowState = FormWindowState.Normal;
            AttributeWindow.BringToFront();//把属性窗口放到最前端展示
        }


        /// <summary>
        /// 右键打开快捷菜单
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_MouseClick(object sender, MouseEventArgs e)
        {
            //右键打开快捷菜单
            if (e.Button == MouseButtons.Right)
            {
                contextMenuStrip1.Show(this.PointToScreen(new Point(e.X, e.Y)));
            }

        }

        /// <summary>
        /// 使地图大小适应窗口大小
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_Resize(object sender, EventArgs e)//存在bug：更改窗口大小时还需要点击“显示全图”
        {
            if (View != null)
            {
                UpdateMap();
            }
        }



        /// <summary>
        /// 更新属性表窗口
        /// </summary>
        private void UpdateAttributeWindow()
        {
            if (Document.IsEmpty())
                return;
            foreach (ShowAttribute AttributeWindow in AllAttwindows.Values)
            {
                if (AttributeWindow == null)
                    continue;
                if (AttributeWindow.IsDisposed)//属性窗口资源已被释放
                    continue;
                AttributeWindow.UpdateData();
            }
        }


        /// <summary>
        /// 更新状态栏信息
        /// </summary>
        public void UpdateStatusBar()
        {
            SelectedFeaturesCount.Text = "当前地图文档中的图层数量为：" + Document.layers.Count.ToString();
        }



        /// <summary>
        /// 重绘窗体
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            if (View != null)
            {
                if (BackWindow != null)
                {
                    //是鼠标操作引起的窗口重绘
                    if (MouseOnMap)
                    {
                        //由于移动地图造成的，就移动背景图片
                        if (MouseCommand == MOUSECOMMAND.Pan || MouseButtons == MouseButtons.Middle)
                        {
                            e.Graphics.DrawImage(BackWindow, MouseMovingX -
                                MouseStartX, MouseMovingY - MouseStartY);
                        }
                        //由于选择或缩放操作造成的，就画一个框
                        else if (MouseCommand != MOUSECOMMAND.Unused && MouseButtons != MouseButtons.Middle)
                        {
                            e.Graphics.DrawImage(BackWindow, 0, 0);
                            e.Graphics.FillRectangle(new SolidBrush(GISConst.ZoomSelectBoxColor),
                                new Rectangle(
                                    Math.Min(MouseStartX, MouseMovingX),
                                    Math.Min(MouseStartY, MouseMovingY),
                                    Math.Abs(MouseStartX - MouseMovingX),
                                    Math.Abs(MouseStartY - MouseMovingY)));
                        }
                    }
                    //如果是滚轮引起的重绘，就直接复制背景窗口
                    else if(delta!=0)
                        e.Graphics.DrawImage(BackWindow, 0, 0);
                    //如果不是鼠标引起的重绘，就直接复制背景窗口
                    else
                        e.Graphics.DrawImage(BackWindow, 0, 0);
                }
            }
        }



        private void layerControlToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LayerControler LayerControl = new LayerControler(Document, this);
            LayerControl.Show();
        }
        private void openDocumentToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "GIS Document" + "|*." + GISConst.MYDOC;
            openFileDialog.RestoreDirectory = false;
            openFileDialog.FilterIndex = 1;
            openFileDialog.Multiselect = false;
            if (openFileDialog.ShowDialog() != DialogResult.OK)
                return;
            Document.Read(openFileDialog.FileName);
            if (Document.IsEmpty() == false)
                UpdateMap();
        }

        private void fullExtentToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (Document.IsEmpty() || View == null)
                return;
            View.UpdateExtent(Document.extent);
            UpdateMap();
        }

        private void Form1_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                MouseStartX = e.X;
                MouseStartY = e.Y;
                MouseOnMap = (e.Button == MouseButtons.Left && MouseCommand != MOUSECOMMAND.Unused);
            }
            if (e.Button == MouseButtons.Middle)//当按下鼠标中键时，代表拖动地图
            {
                MouseStartX = e.X;
                MouseStartY = e.Y;
                MouseOnMap = (e.Button == MouseButtons.Middle);
                Cursor = Cursors.Hand;//光标变为手型
            }
        }

        private void Form1_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                MouseMovingX = e.X;
                MouseMovingY = e.Y;
                if (MouseOnMap)
                    Invalidate();//引发Paint事件，让窗体重绘
            }
            if (e.Button == MouseButtons.Middle)
            {
                MouseMovingX = e.X;
                MouseMovingY = e.Y;
                if (MouseOnMap)
                    Invalidate();//引发Paint事件，让窗体重绘
            }
        }

        private void Form1_MouseUp(object sender, MouseEventArgs e)
        {
            if (Document.IsEmpty())
                return;
            if (MouseOnMap == false)
                return;
            MouseOnMap = false;

            if (e.Button == MouseButtons.Left)
            {
                switch (MouseCommand)
                {
                    case MOUSECOMMAND.Select:
                        //如果control键没被按住，就清空选择集
                        if (Control.ModifierKeys != Keys.Control)
                        {
                            Document.ClearSelection();
                        }
                        SelectResult sr = SelectResult.UnknownType;
                        if (e.X == MouseStartX && e.Y == MouseStartY)
                        {
                            //点选
                            GISVertex v = View.ToMapVertex(new Point(e.X, e.Y));
                            sr = Document.Select(v, View);
                        }
                        else
                        {
                            //框选
                            GISExtent extent = View.RectToExtent(e.X, MouseStartX, e.Y, MouseStartY);
                            sr = Document.Select(extent);
                        }
                        //仅当选择集最可能发生变化时，才更新地图和属性窗口
                        if (sr == SelectResult.OK || Control.ModifierKeys != Keys.Control)
                        {
                            UpdateMap();
                            UpdateAttributeWindow();
                        }
                        break;
                    case MOUSECOMMAND.ZoomIn:
                        if (e.X == MouseStartX && e.Y == MouseStartY)//单点放大
                        {
                            GISVertex MouseLocation = View.ToMapVertex(new Point(e.X, e.Y));
                            GISExtent E1 = View.GetRealExtent();//当前地图范围
                            double newwidth = E1.getWidth() * GISConst.ZoomInFactor;
                            double newheight = E1.getHeight() * GISConst.ZoomInFactor;
                            double newminx = MouseLocation.x - (MouseLocation.x - E1.getMinX()) * GISConst.ZoomInFactor;
                            double newminy = MouseLocation.y - (MouseLocation.y - E1.getMinY()) * GISConst.ZoomInFactor;
                            View.UpdateExtent(new GISExtent(newminx, newminx + newwidth, newminy, newminy + newheight));
                        }
                        else//拉框放大
                        {
                            View.UpdateExtent(View.RectToExtent(e.X, MouseStartX, e.Y, MouseStartY));
                        }
                        UpdateMap();
                        break;
                    case MOUSECOMMAND.ZoomOut:
                        if (e.X == MouseStartX && e.Y == MouseStartY)//单点缩小
                        {
                            GISExtent E1 = View.GetRealExtent();
                            GISVertex MouseLocation = View.ToMapVertex(new Point(e.X, e.Y));
                            double newwidth = E1.getWidth() / GISConst.ZoomOutFactor;
                            double newheight = E1.getHeight() / GISConst.ZoomOutFactor;
                            double newminx = MouseLocation.x - (MouseLocation.x - E1.getMinX()) / GISConst.ZoomOutFactor;
                            double newminy = MouseLocation.y - (MouseLocation.y - E1.getMinY()) / GISConst.ZoomOutFactor;
                            View.UpdateExtent(new GISExtent(newminx, newminx + newwidth, newminy, newminy + newheight));
                        }
                        else//拉框缩小
                        {
                            GISExtent E3 = View.RectToExtent(e.X, MouseStartX, e.Y, MouseStartY);//拉框范围
                            GISExtent E1 = View.GetRealExtent();//当前地图范围
                            double newwidth = E1.getWidth() * E1.getWidth() / E3.getWidth();
                            double newheight = E1.getHeight() * E1.getHeight() / E3.getHeight();
                            double newminx = E3.getMinX() - (E3.getMinX() - E1.getMinX()) * newwidth / E1.getWidth();
                            double newminy = E3.getMinY() - (E3.getMinY() - E1.getMinY()) * newheight / E1.getHeight();
                            View.UpdateExtent(new GISExtent(newminx, newminx + newwidth, newminy, newminy + newheight));
                        }
                        UpdateMap();
                        break;
                    case MOUSECOMMAND.Pan:
                        if (e.X != MouseStartX || e.Y != MouseStartY)
                        {
                            GISExtent E1 = View.GetRealExtent();
                            GISVertex M1 = View.ToMapVertex(new Point(MouseStartX, MouseStartY));//鼠标按下时地图的位置
                            GISVertex M2 = View.ToMapVertex(new Point(e.X, e.Y));//鼠标抬起时地图的位置
                            double newwidth = E1.getWidth();
                            double newheight = E1.getHeight();
                            double newminx = E1.getMinX() - (M2.x - M1.x);
                            double newminy = E1.getMinY() - (M2.y - M1.y);
                            View.UpdateExtent(new GISExtent(newminx, newminx + newwidth, newminy, newminy + newheight));
                            UpdateMap();
                        }
                        break;
                }
            }

            if (e.Button == MouseButtons.Middle)//中键：拖动地图
            {
                if (e.X != MouseStartX || e.Y != MouseStartY)
                {
                    GISExtent E1 = View.GetRealExtent();
                    GISVertex M1 = View.ToMapVertex(new Point(MouseStartX, MouseStartY));//鼠标按下时地图的位置
                    GISVertex M2 = View.ToMapVertex(new Point(e.X, e.Y));//鼠标抬起时地图的位置
                    double newwidth = E1.getWidth();
                    double newheight = E1.getHeight();
                    double newminx = E1.getMinX() - (M2.x - M1.x);
                    double newminy = E1.getMinY() - (M2.y - M1.y);
                    View.UpdateExtent(new GISExtent(newminx, newminx + newwidth, newminy, newminy + newheight));
                    UpdateMap();
                }
                Cursor = Cursors.Default;
            }

        }

        private void 选择ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MouseCommand = MOUSECOMMAND.Select;
        }

        private void 放大ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MouseCommand = MOUSECOMMAND.ZoomIn;
        }

        private void 缩小ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MouseCommand = MOUSECOMMAND.ZoomOut;
        }

        private void 拖动地图ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MouseCommand = MOUSECOMMAND.Pan;
        }


        /// <summary>
        /// “清空选择”按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ClearSelectionButton_Click(object sender, EventArgs e)
        {
            Document.ClearSelection();
            UpdateMap();
        }

        private void Form1_MouseWheel(object sender, MouseEventArgs e)
        {
            delta = e.Delta; // 获取滚轮滚动的增量值
            //向上滚动，放大
            if (delta > 0)
            {
                GISVertex MouseLocation = View.ToMapVertex(new Point(e.X, e.Y));
                GISExtent E1 = View.GetRealExtent();//当前地图范围
                double newwidth = E1.getWidth() * GISConst.ZoomInFactor;
                double newheight = E1.getHeight() * GISConst.ZoomInFactor;
                double newminx = MouseLocation.x - (MouseLocation.x - E1.getMinX()) * GISConst.ZoomInFactor;
                double newminy = MouseLocation.y - (MouseLocation.y - E1.getMinY()) * GISConst.ZoomInFactor;
                View.UpdateExtent(new GISExtent(newminx, newminx + newwidth, newminy, newminy + newheight));
            }
            //向下滚动，缩小
            else if (delta < 0)
            {
                GISExtent E1 = View.GetRealExtent();
                GISVertex MouseLocation = View.ToMapVertex(new Point(e.X, e.Y));
                double newwidth = E1.getWidth() / GISConst.ZoomOutFactor;
                double newheight = E1.getHeight() / GISConst.ZoomOutFactor;
                double newminx = MouseLocation.x - (MouseLocation.x - E1.getMinX()) / GISConst.ZoomOutFactor;
                double newminy = MouseLocation.y - (MouseLocation.y - E1.getMinY()) / GISConst.ZoomOutFactor;
                View.UpdateExtent(new GISExtent(newminx, newminx + newwidth, newminy, newminy + newheight));
            }
        }

    }
}
